package com.oss.service.system;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.oss.common.BaseResponse;
import com.oss.dto.role.RoleAddDto;
import com.oss.dto.role.RoleDeleteDto;
import com.oss.dto.role.RolePageDto;
import com.oss.dto.role.RoleUpdateDto;
import com.oss.entity.system.Rights;
import com.oss.entity.system.Role;
import com.oss.entity.system.RoleRights;
import com.oss.enums.IsDeletedEnum;
import com.oss.enums.UserStatusEnum;
import com.oss.mapper.system.RightsMapper;
import com.oss.mapper.system.RoleMapper;
import com.oss.mapper.system.RoleRightsMapper;
import com.oss.mapper.system.SystemMapper;
import com.oss.util.SnowFlakeUtil;
import com.oss.util.TimeUtil;
import com.oss.vo.role.RoleDetailVO;
import com.oss.vo.role.RoleVO;
import com.oss.vo.role.UserRoleVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author chengqiang
 */
@Service
public class RoleService extends ServiceImpl<RoleMapper, Role> {
    @Autowired
    TimeUtil timeUtil;
    @Autowired
    RoleMapper roleMapper;
    @Autowired
    RoleRightsMapper roleRightsMapper;
    @Autowired
    UserService userService;
    @Autowired
    RightsService rightsService;
    @Autowired
    RightsMapper rightsMapper;
    @Autowired
    SystemMapper systemMapper;

    public IPage<RoleVO> selectByPage(RolePageDto dto) {
        LambdaQueryWrapper<Role> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Role::getIsDeleted, IsDeletedEnum.NO.getFlag());
        lambdaQueryWrapper.eq(StringUtils.isNotBlank(dto.getRoleName()), Role::getRoleName, dto.getRoleName());
        lambdaQueryWrapper.in(CollectionUtils.isNotEmpty(dto.getRoleStatusList()), Role::getRoleStatus, dto.getRoleStatusList());
        lambdaQueryWrapper.orderByDesc(Role::getCreateTime);
        IPage<Role> ipage = this.page(new Page(dto.getPageNo(),dto.getPageSize()),lambdaQueryWrapper);
        Set<String> creatorIdSet = ipage.getRecords().stream().map(Role::getCreatorId).collect(Collectors.toSet());
        Map<String,String> userMap = userService.selectByIds(creatorIdSet);
        if (CollectionUtils.isNotEmpty(ipage.getRecords())) {
            // 父菜单map key = id, value = 菜单名称
            return ipage.convert(entity->{
                RoleVO vo = new RoleVO();
                BeanUtils.copyProperties(entity,vo);
                vo.setRoleStatusName(UserStatusEnum.getStatusEnumsDescByKey(entity.getRoleStatus()));
                vo.setCreatorName(userMap.get(entity.getCreatorId()));
                return vo;
            });
        }
        return null;
    }

    public BaseResponse addRole(RoleAddDto dto) {
        LambdaQueryWrapper<Role> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Role::getIsDeleted, IsDeletedEnum.NO.getFlag());
        lambdaQueryWrapper.eq(StringUtils.isNotBlank(dto.getRoleName()), Role::getRoleName, dto.getRoleName());
        long count = this.count(lambdaQueryWrapper);
        if (count > 0) {
            return BaseResponse.error("角色已存在");
        }
        Role entity = new Role();
        BeanUtils.copyProperties(dto,entity);
        entity.setRoleId(SnowFlakeUtil.getID());
        entity.setRoleStatus(1);
        // 默认父角色ID=0
        if(StringUtils.isBlank(dto.getParentRoleId())) {
            entity.setParentRoleId("0");
        }
        roleMapper.insert(entity);
        if (CollectionUtils.isNotEmpty(dto.getRightsIdList())) {
            Set<String> rightsIds = rightsService.getRightsList(dto.getRightsIdList());
            for (String rightsId : rightsIds) {
                RoleRights roleRightsEntity = new RoleRights();
                roleRightsEntity.setRoleId(entity.getRoleId());
                roleRightsEntity.setRightsId(rightsId);
                roleRightsMapper.insert(roleRightsEntity);
            }
        }
        return BaseResponse.success("操作成功");
    }
    public BaseResponse updateRole(RoleUpdateDto dto) {
        LambdaQueryWrapper<Role> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Role::getIsDeleted, IsDeletedEnum.NO.getFlag());
        lambdaQueryWrapper.ne(Role::getRoleId, dto.getRoleId());
        lambdaQueryWrapper.eq(StringUtils.isNotBlank(dto.getRoleName()), Role::getRoleName, dto.getRoleName());
        long count = this.count(lambdaQueryWrapper);
        if (count > 0) {
            return BaseResponse.error("角色已存在");
        }
        // 1. 修改角色的基本信息
        LambdaUpdateWrapper<Role> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.eq(Role::getRoleId,dto.getRoleId());
        Role entity = new Role();
        BeanUtils.copyProperties(dto,entity);
        roleMapper.update(entity,lambdaUpdateWrapper);
        // 2.删除当前角色的角色和权限的关联表信息
        LambdaUpdateWrapper<RoleRights> roleRightsLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        roleRightsLambdaUpdateWrapper.eq(RoleRights::getIsDeleted,IsDeletedEnum.NO.getFlag());
        roleRightsLambdaUpdateWrapper.set(RoleRights::getIsDeleted,IsDeletedEnum.YES.getFlag());
        roleRightsLambdaUpdateWrapper.eq(RoleRights::getRoleId,dto.getRoleId());
        roleRightsMapper.update(null,roleRightsLambdaUpdateWrapper);
        // 3.插入角色和关联表的关联信息
        Set<String> rightsIds = rightsService.getRightsList(dto.getRightsIdList());
        for (String rightsId : rightsIds) {
            RoleRights roleRightsEntity = new RoleRights();
            roleRightsEntity.setRoleId(dto.getRoleId());
            roleRightsEntity.setRightsId(rightsId);
            roleRightsMapper.insert(roleRightsEntity);
        }
        return BaseResponse.success("操作成功");
    }

    public String deleteRole(RoleDeleteDto dto) {
        LambdaUpdateWrapper<Role> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.set(Role::getIsDeleted,IsDeletedEnum.YES.getFlag());
        lambdaUpdateWrapper.eq(Role::getRoleId,dto.getRoleId());
        roleMapper.update(null,lambdaUpdateWrapper);
        return "操作成功";
    }

    public List<RoleVO> listAll(RolePageDto dto) {
        LambdaQueryWrapper<Role> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.like(StringUtils.isNotBlank(dto.getRoleName()), Role::getRoleName, dto.getRoleName());
        lambdaQueryWrapper.eq(Role::getIsDeleted,IsDeletedEnum.NO.getFlag());
        lambdaQueryWrapper.orderByDesc(Role::getCreateTime);
        List<Role> listAll = roleMapper.selectList(lambdaQueryWrapper);
        if(CollectionUtils.isNotEmpty(listAll)){
            Set<String> userIDSet = listAll.stream().map(Role::getCreatorId).collect(Collectors.toSet());
            Map<String,String> userMap = userService.selectByIds(userIDSet);
            List<RoleVO> listVO = listAll.stream().map(entity->{
                RoleVO vo = new RoleVO();
                BeanUtils.copyProperties(entity,vo);
                vo.setCreatorName(userMap.get(entity.getCreatorId()));
                return vo;
            }).collect(Collectors.toList());
            return recursionRole(listVO,"0");
        } else {
            return new ArrayList<>();
        }
    }

    /**
     * 递归处理全部角色列表
     * @param list 角色列表
     * @return 返回角色列表
     */
    public List<RoleVO> recursionRole(List<RoleVO> list,String parentRoleId){
        List<RoleVO> returnList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(list)){
            list.forEach(role->{
                if (role.getParentRoleId().equals(parentRoleId)) {
                    List<RoleVO> children = recursionRole(list,role.getRoleId());
                    role.setChildren(children);
                    returnList.add(role);
                }
            });
        }
        return  returnList;
    }


    public BaseResponse getOneById(String roleId) {
        BaseResponse baseResponse = new BaseResponse<>();
        baseResponse.setCode(1);
        Role entity = roleMapper.selectById(roleId);
        RoleDetailVO vo = new RoleDetailVO();
        BeanUtils.copyProperties(entity,vo);
        baseResponse.setData(vo);
        baseResponse.setExtraData(new ArrayList<>());
        LambdaQueryWrapper<RoleRights> roleRightsLambdaQueryWrapper = new LambdaQueryWrapper<>();
        roleRightsLambdaQueryWrapper.eq(RoleRights::getRoleId,roleId);
        roleRightsLambdaQueryWrapper.eq(RoleRights::getIsDeleted,IsDeletedEnum.NO.getFlag());
        List<String> rightsIds = roleRightsMapper.selectList(roleRightsLambdaQueryWrapper).stream().map(RoleRights::getRightsId).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(rightsIds)){
            return baseResponse;
        }
        rightsIds = removeHasNoAllChildrenNodeParentId(rightsIds);
        if (CollectionUtils.isEmpty(rightsIds)){
            return baseResponse;
        }
        List<Rights> rightsList = rightsMapper.selectBatchIds(rightsIds);
        // 按钮权限
        List<String> btnRightsList = rightsList.stream().filter(item->item.getRightsType()==2).map(Rights::getRightsId).collect(Collectors.toList());
        // 非按钮权限(菜单)
        List<String> menuRightsList = rightsList.stream().filter(item->item.getRightsType()!=2).map(Rights::getRightsId).collect(Collectors.toList());
        vo.setRightsIdList(menuRightsList);
        baseResponse.setExtraData(btnRightsList);
        // 全部菜单
        LambdaQueryWrapper<Rights> rightsLambdaQueryWrapper = new LambdaQueryWrapper<>();
        rightsLambdaQueryWrapper.eq(Rights::getIsDeleted,IsDeletedEnum.NO.getFlag());
        List<Rights> allRights = rightsMapper.selectList(rightsLambdaQueryWrapper);
        vo.setRightsList(allRights);
        return baseResponse;
    }

    /**
     * 如果父节点下的子节点不全 , 就删除父节点
     * @param rightsIds 某角色的权限IDList
     * @return
     */
    public List<String> removeHasNoAllChildrenNodeParentId(List<String> rightsIds){
        List<String> returnList = new ArrayList<>();
        LambdaQueryWrapper<Rights> rightsLambdaQueryWrapper = new LambdaQueryWrapper<>();
        rightsLambdaQueryWrapper.eq(Rights::getIsDeleted,IsDeletedEnum.NO.getFlag());
        rightsLambdaQueryWrapper.ne(Rights::getRightsType,2);
        // 全部菜单(不包含按钮)
        List<Rights> allRights = rightsMapper.selectList(rightsLambdaQueryWrapper);
        for (String rightsId : rightsIds) {
            // 当前菜单的全部子节点
            List<Rights> childrenList = allRights.stream().filter(item->item.getParentRightsId().equals(rightsId)).collect(Collectors.toList());
            // 当前菜单有子菜单
            if (CollectionUtils.isNotEmpty(childrenList)){
                List<String> childrenIds = childrenList.stream().map(Rights::getRightsId).collect(Collectors.toList());
                // 权限列表,包含的当前菜单的所有子菜单
                boolean flag = rightsIds.containsAll(childrenIds);
                if (flag == true){
                    returnList.add(rightsId);
                }
            } else {
                // 当前菜单没有子菜单
                returnList.add(rightsId);
            }
        }
        return returnList;
    }

    /**
     * 若权限父ID和子ID同时存在, 剔除父ID, 否则返回的数据既有子ID又有父ID,会导致全选这个父ID下面的权限
     * @param rightsIds 权限ID集合
     * @return 返回权限ID
     */
    public List<String> removeParentId(List<String> rightsIds) {
        if(CollectionUtils.isNotEmpty(rightsIds)){
            // 待去除ID
            Set<String> ids = new HashSet<>();
            // 权限map key = 权限ID,value=父ID
            Map<String,String> map = rightsMapper.selectBatchIds(rightsIds).stream().collect(Collectors.toMap(Rights::getRightsId, Rights::getParentRightsId,(v1, v2)->v2));
            for (String id : rightsIds) {
                if (map.containsKey(id)) {
                    String parentId = map.get(id);
                    // 如果父ID在集合中
                    if (rightsIds.contains(parentId)){
                        ids.add(parentId);
                    }
                }
            }
            rightsIds.removeAll(ids);
        }
        return  rightsIds;
    }


    /**
     * 获取用户的角色信息
     * @param userIdSet 用户ID
     * @return 返回角色map key=用户ID,value=角色名称数组
     */
    public Map<String, List<String>> selectRightsByUserId(Set<String> userIdSet) {
        if (CollectionUtils.isNotEmpty(userIdSet)){
            List<UserRoleVO> list = systemMapper.getRoleNameByUserId(userIdSet);
            // 按用户分组
            Map<String,List<UserRoleVO>> map = list.stream().collect(Collectors.groupingBy(UserRoleVO::getUserId));
            Map<String, List<String>> returnMap = new HashMap<>();
            map.forEach((key,value)->{
                Set<String> roleNameSet = value.stream().map(UserRoleVO::getRoleName).collect(Collectors.toSet());
                returnMap.put(key,new ArrayList<>(roleNameSet));
            });
            return returnMap;
        } else {
            return new HashMap<>();
        }
    }
}
